package com.xh.bussiness.exam.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xh.bussiness.exam.bean.ErrorClassStudent;
import com.xh.bussiness.exam.bean.dto.*;
import com.xh.bussiness.exam.bean.request.StudentErrorTotalStatRequest;
import com.xh.bussiness.exam.bean.request.UserErrorQuestionRequest;
import com.xh.bussiness.exam.bean.request.UserErrorQuestionSaveRequest;
import com.xh.bussiness.exam.dao.UserErrorQuestionMapper;
import com.xh.bussiness.exam.model.UserErrorQuestion;
import com.xh.bussiness.exam.model.UserErrorQuestionCorrectLog;
import com.xh.bussiness.exam.service.IPaperQuestionTestDetailService;
import com.xh.bussiness.exam.service.IUserErrorQuestionCorrectLogService;
import com.xh.bussiness.exam.service.IUserErrorQuestionService;
import com.xh.bussiness.practice.service.IPracticeStudentResultService;
import com.xh.bussiness.system.bean.dto.DictionaryBean;
import com.xh.bussiness.system.bean.dto.StudentBean;
import com.xh.bussiness.system.service.IDictionaryService;
import com.xh.bussiness.system.service.IStudentService;
import com.xh.bussiness.tiku.bean.dto.QuestionDto;
import com.xh.bussiness.tiku.constant.PaperConstant;
import com.xh.bussiness.tiku.model.Knowledge;
import com.xh.bussiness.tiku.model.Question;
import com.xh.bussiness.tiku.service.IKnowledgeService;
import com.xh.bussiness.tiku.service.IQuestionService;
import com.xh.core.bean.XhPage;
import com.xh.core.service.impl.BaseServiceImpl;
import com.xh.core.util.DateUtils;
import com.xh.core.util.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;

/*
 * @Author daiwei
 * @Description
 * @Date 2019/4/16 14:59
 **/
@Service
public class UserErrorQuestionServiceImpl
        extends BaseServiceImpl<UserErrorQuestionMapper, UserErrorQuestion>
        implements IUserErrorQuestionService {

    Logger log = LoggerFactory.getLogger(UserErrorQuestionServiceImpl.class);

    @Autowired
    private IUserErrorQuestionCorrectLogService logService;
    @Autowired
    private IQuestionService questionService;
    @Autowired
    private IKnowledgeService knowledgeService;
    @Autowired
    private IDictionaryService dictionaryService;
    @Autowired
    private IStudentService studentService;
    @Autowired
    private IPaperQuestionTestDetailService paperQuestionTestDetailService;
    @Autowired
    private IPracticeStudentResultService studentResultService;


    @Override
    public List<String> addUserErrorQuestion(UserErrorQuestionSaveRequest bean) {
        List<String> studentIds = null;
        if (!StringUtils.isEmpty(bean.getStudentId())) {
            studentIds = Arrays.asList(bean.getStudentId().split(","));
        }
        List<String> userErrorQues = new ArrayList<>();
        if (!CollectionUtils.isEmpty(studentIds)) {
            for (String studentId : studentIds) {
                QueryWrapper<UserErrorQuestion> qw = new QueryWrapper<>();
                qw.eq("question_id", bean.getQuestionId());
                qw.eq("question_version",studentId);
                qw.eq("student_id", bean.getStudentId());
                //qw.eq("status", 0);

                UserErrorQuestion userErrorQuestion = this.dao.selectOne(qw);
                if (userErrorQuestion == null) {
                    userErrorQuestion = new UserErrorQuestion();
                    //老师拍的/学生拍的
                    userErrorQuestion.setSourceType(bean.getSourceType());
                    userErrorQuestion.setStatus(bean.getStatus());
                    userErrorQuestion.setErrorCount(1);
                } else {
                    userErrorQuestion.setErrorCount(userErrorQuestion.getErrorCount() + 1);
                    //更新到最新时间
                    userErrorQuestion.setCreateTime(new Date());
                }
                userErrorQuestion.setQuestionSource(bean.getQuestionSource());
                userErrorQuestion.setErrorReason(bean.getErrorReason());
                userErrorQuestion.setSubjectId(bean.getSubjectId());
                userErrorQuestion.setGradeId(bean.getGradeId());
                userErrorQuestion.setQuestionId(bean.getQuestionId());
                userErrorQuestion.setQuestionVersion(bean.getQuestionVersion());
                userErrorQuestion.setUserId(bean.getUserId());
                userErrorQuestion.setStudentId(studentId);
                userErrorQuestion.setUserAnswer(bean.getUserAnswer());
                userErrorQuestion.setImgPath(bean.getImgPath());
                userErrorQuestion.setOldImgPath(bean.getOldImgPath());
                userErrorQuestion.insertOrUpdate();

                userErrorQues.add(userErrorQuestion.getId());

                //保存日志
                UserErrorQuestionCorrectLog log = new UserErrorQuestionCorrectLog();
                BeanUtils.copyProperties(userErrorQuestion, log);
                log.setId(null);
                log.setStatus(0);
                logService.insert(log);
            }
        }
        return userErrorQues;
    }

    @Override
    public UserErrorQuestion queryUserErrorQuestionByStuIdAndQuesId(String studentId, String questionId) {
        QueryWrapper<UserErrorQuestion> questionQueryWrapper = new QueryWrapper<>();
        questionQueryWrapper.eq("student_id", studentId);
        questionQueryWrapper.eq("question_id", questionId);
        return this.dao.selectOne(questionQueryWrapper);
    }

    @Override
    public List<UserErrorQuestion> queryUserErrorQuestion(UserErrorQuestionRequest bean) {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public XhPage<UserErrorQuestionDto> queryUserErrorQuestionPage(XhPage<UserErrorQuestionDto> page, UserErrorQuestionRequest bean) {
        // TODO 根据知识点查询所有子节点
        List<String> knowledgeIds = new ArrayList<String>();
        if (bean.getKnowledgeId() != null) {
            QueryWrapper<Knowledge> qw = new QueryWrapper<Knowledge>();
            qw.like("parent_path", "-" + bean.getKnowledgeId() + "-").or().eq("id", bean.getKnowledgeId());
            List<Knowledge> knowledges = knowledgeService.queryByCondition(qw);
            knowledges.forEach(k -> {
                knowledgeIds.add(k.getId());
            });
        }
        if (!CollectionUtils.isEmpty(knowledgeIds)) {
            bean.setKnowledgeIds(knowledgeIds);
        }
        //bean.setUserId(UserUtils.getCurrentUserId());
        this.dao.queryByParam(page, bean);
        List<UserErrorQuestionDto> list = page.getRecords();
        List<String> questionIds = studentResultService.queryHighFrequencyErrorQuestion(bean.getClassId(),null);
        list.forEach(eq -> {
            QuestionDto question = questionService.getQuestion(eq.getQuestionId(), eq.getQuestionVersion());
            if(questionIds.contains(question.getId())){
                eq.setHigh(true);
            }
            eq.setQuestion(question);
        });
        return page;
    }

    @Override
    public List<Map<String, Object>> queryCountBySubject(String studentId) {

        return this.dao.queryCountBySubject(studentId);
    }

    @Override
    public List<Map<String, Object>> queryCountByCalendar(String studentId, Integer year, Integer month) {
        Calendar calendar = Calendar.getInstance();
        if (year == null) {
            year = calendar.get(Calendar.YEAR);
        }
        if (month == null) {
            month = calendar.get(Calendar.MONTH + 1);
        }
        return this.dao.queryCountByCalendar(studentId, year, month);
    }

    @Override
    public StudentErrorTotalStatDto queryStudentErrorTotalStat(StudentErrorTotalStatRequest request) {
        StudentErrorTotalStatDto result = new StudentErrorTotalStatDto();
        StudentBean student = studentService.getById(request.getStudentId(), StudentBean.class);
        DictionaryBean gradeType = dictionaryService.getById(request.getGradeRange(), DictionaryBean.class);
        DictionaryBean subject = dictionaryService.getById(request.getSubjectId(), DictionaryBean.class);
        result.setGradeType(gradeType);
        result.setSubject(subject);
        result.setStudent(student);
        request.setPaperType(PaperConstant.TYPE.ERROR_QUESTION_TEST);

        List<Map<String, Object>> errorStatList = this.dao.queryStudentErrorQuestionByGradeTypeAndSubject(request);
        List<Map<String, Object>> testDetailStatList = this.paperQuestionTestDetailService.queryStudentTestDetailByGradeTypeAndSubject(request);

        result.calc(errorStatList, testDetailStatList);

        return result;
    }

    @Override
    public XhPage<UserErrorQuestionDto> queryStuErrorQuestionIdByDate(XhPage page, String studentId, String date) {
        if (StringUtils.isEmpty(studentId) || StringUtils.isEmpty(date)) {
            return new XhPage<>();
        }
//        List<UserErrorQuestionListDto> resultList = new ArrayList<>();
        //根据日志查询学生错题数据
        XhPage<UserErrorQuestionDto> userErrorQuestions = this.dao.queryStuErrorQuestionIdByDate(page, studentId, date);
        List<UserErrorQuestionDto> records = userErrorQuestions.getRecords();
        if (!CollectionUtils.isEmpty(userErrorQuestions.getRecords())) {
//            UserErrorQuestionListDto dto = null;
            for (UserErrorQuestionDto userErrorQuestion : records) {
                QuestionDto question = questionService.getQuestion(userErrorQuestion.getQuestionId(), userErrorQuestion.getQuestionVersion(), false,false,false,false,false);
                if (question == null) {
                    log.error(String.format("queryStuErrorQuestionIdByDate(%s,%s) question is null", userErrorQuestion.getQuestionId(), userErrorQuestion.getQuestionVersion()));
                    continue;
                }
                userErrorQuestion.setQuestion(question);
//                dto = new UserErrorQuestionListDto();
//                dto.setErrorUserQuestionId(userErrorQuestion.getId());
//                String questionSource = userErrorQuestion.getQuestionSource();
//                if (!StringUtils.isEmpty(questionSource)) {
//                    String[] sources = questionSource.split(",");
//                    dto.setErrorQuestionSourceLabel(Arrays.asList(sources));
//                }
//                String questionReason = userErrorQuestion.getErrorReason();
//                if (!StringUtils.isEmpty(questionReason)) {
//                    String[] reasons = questionReason.split(",");
//                    dto.setErrorQuestionReasonLabel(Arrays.asList(reasons));
//                }
//                dto.setQuestionDto(question);
//                dto.setCreateDate(DateUtils.format(userErrorQuestion.getCreateTime(), "yyyy-MM-dd"));
//                if (userErrorQuestion.getStatus().equals(1)) {
//                    dto.setCorrectStatus("已订正");
//                } else {
//                    dto.setCorrectStatus("未订正");
//                }
//                resultList.add(dto);

            }
        }
//        page.setRecords(resultList);
        return page;
    }

    @Override
    public UserErrorQuestionDetailsDto queryUserErrorQuestionDetail(String userErrorQuestionId) {
        if (StringUtils.isEmpty(userErrorQuestionId)) {
            return new UserErrorQuestionDetailsDto();
        }
        UserErrorQuestionDetailsDto detailsDto = new UserErrorQuestionDetailsDto();
        UserErrorQuestion userErrorQuestion = this.getById(userErrorQuestionId);
        if (userErrorQuestion == null) {
            log.error(String.format("queryUserErrorQuestionDetail(%s) is null", userErrorQuestionId));
            return new UserErrorQuestionDetailsDto();
        }
        QuestionDto question = null;
        if (!StringUtils.isEmpty(userErrorQuestion.getQuestionId())) {
            question = questionService.getQuestion(userErrorQuestion.getQuestionId(), userErrorQuestion.getQuestionVersion(), true,false,false,false,false);
            if (question == null) {
                log.error(String.format("queryUserErrorQuestionDetail question by %s is null", userErrorQuestion.getQuestionId()));
                return new UserErrorQuestionDetailsDto();
            }
        }
        //错题来源
        String questionSource = userErrorQuestion.getQuestionSource();
        if (!StringUtils.isEmpty(questionSource)) {
            String[] questionSources = questionSource.split(",");
            detailsDto.setErrorQuestionSourceLabel(Arrays.asList(questionSources));
        }
        //错题原因
        String questionReason = userErrorQuestion.getErrorReason();
        if (!StringUtils.isEmpty(questionReason)) {
            String[] questionReasonLabels = questionReason.split(",");
            detailsDto.setErrorQuestionReasonLabel(Arrays.asList(questionReasonLabels));
        }
        detailsDto.setUserErrorQuestionId(userErrorQuestion.getId());
        detailsDto.setCreateTime(DateUtils.format(userErrorQuestion.getCreateTime(), "yyyy-MM-dd"));
        detailsDto.setQuestionDto(question);
        detailsDto.setUploadErrorQuesImg(userErrorQuestion.getImgPath());
        detailsDto.setOldUploadErrorQuesImg(userErrorQuestion.getOldImgPath());
        return detailsDto;
    }

    @Override
    public StudentReportForAppletDto queryStudentReportForApplet(String studentId) {
        //查过去30天的错题数据
        Calendar now = Calendar.getInstance();
        String endDate = DateUtils.format(now.getTime(), "yyyy-MM-dd HH:mm:ss");
        now.add(Calendar.DAY_OF_MONTH, -30);
        String startDate = DateUtils.format(now.getTime(), "yyyy-MM-dd HH:mm:ss");


        List<Map<String, Object>> userErrorQuestions = this.dao.queryUserErrorQuestions(studentId, startDate, endDate);
        if (CollectionUtils.isEmpty(userErrorQuestions)) {
            log.warn(String.format("queryStudentReportForApplet(%s) result is null", studentId));
            return new StudentReportForAppletDto();
        }
        List<Map<String, String>> knowledgeAnalyses = this.dao.queryUserErrorQuesKnowledge(studentId, startDate, endDate);
        StudentReportForAppletDto dto = new StudentReportForAppletDto();
        dto.calc(userErrorQuestions, knowledgeAnalyses);
        return dto;
    }

    @Override
    public Integer queryCorrectCountByStuId(String studentId, Integer status) {
        QueryWrapper qw = new QueryWrapper();
        qw.eq("student_id", studentId);
        //已订正
        if (status != null) {
            qw.eq("status", status);
        }
        return this.dao.selectCount(qw);
    }

    @Override
    public List<StuErrorQuesKnowledgePointTreeDto> queryStudentErrorQuesKnowledge(String studentId, String subjectId, String gradeRange) {
        List<KnowledgeDto> knowledgeDtos = this.dao.queryStudentErrorQuesKnowledge(studentId, subjectId, gradeRange);
        if (CollectionUtils.isEmpty(knowledgeDtos)) {
            return new ArrayList<>();
        }
        map = new HashMap<>();
        for (KnowledgeDto item : knowledgeDtos) {
            addNode(item);
        }
        return new ArrayList<>(map.values());

    }

    private static Map<String, StuErrorQuesKnowledgePointTreeDto> map;

    private synchronized void addNode(KnowledgeDto item) {
        String[] parentIds = item.getParentPath().split("#");
        String[] parentNames = item.getParentName().split("#");
        Long total = item.getTotal();
        //遍历父节点，倒序处理计数
        for (int i = parentIds.length - 1; i >= 0; i--) {
            //当前父节点ID
            String parentId = parentIds[i];
            if (StringUtils.isEmpty(parentId)) {
                continue;
            }
            StuErrorQuesKnowledgePointTreeDto p = map.get(parentId);
            //判断是否有此节点
            if (p == null) {
                try {
                    //父节点的父节点ID
                    String ppId = i == 1 ? "" : parentIds[i - 1];
                    //当前父节点名称
                    String name = parentNames[i];

                    p = new StuErrorQuesKnowledgePointTreeDto(parentId, ppId, name);
                    p.setCount(total);
                    map.put(parentId, p);
                } catch (Exception e) {
                    log.error(String.format("queryStudentErrorQuesKnowledge addNode param：%s", item.getParentPath()));
                    log.error(String.format("queryStudentErrorQuesKnowledge addNode have error: %s", e.getMessage()));
                }
            } else {
                p.setCount(p.getCount() + total);
            }

        }
    }

    @Override
    public XhPage<UserErrorQuestionDto> queryByPaperId(XhPage<UserErrorQuestionDto> page, String paperId, String studentId) {

        this.dao.queryByPaperId(page, paperId, studentId);
        List<UserErrorQuestionDto> list = page.getRecords();
        list.forEach(eq -> {
            QuestionDto question = questionService.getQuestion(eq.getQuestionId(), eq.getQuestionVersion());
            eq.setQuestion(question);
        });
        return page;
    }

    @Override
    public Integer queryStudentErrorQuesCountByLwStudentId(String studentId) {
        //统计错题数
        Integer errorQuestionCount = this.queryCorrectCountByStuId(studentId, null);
        return errorQuestionCount;
    }

    @Override
    public UserErrorQuestion checkUserErrorQuestion(UserErrorQuestionRequest request) {
        Question question = new Question();
        question.setTitle(request.getQuestionDto().getTitle());
        if (request.getQuestionDto().getOption() != null) {
            question.setOptionContent(request.getQuestionDto().getOption().toJSONString());
        }
        if (request.getQuestionDto().getRightAnswer() != null) {
            question.setRightAnswer(request.getQuestionDto().getRightAnswer().toJSONString());
        }
        String md5 = question.genarateMd5();
        Question ques = questionService.queryByMd5AndSubject(md5, null);
        if (ques == null) {
            return null;
        }
        return this.queryUserErrorQuestionByStuIdAndQuesId(request.getStudentId(), ques.getId());
    }

    @Override
    public void cancelUserErrorQuestion(String[] ids) {
        for (String id : ids) {
            UserErrorQuestion errorQuestion = this.getById(id);
            if (errorQuestion == null) {
                continue;
            }
            if (errorQuestion.getErrorCount() != null && errorQuestion.getErrorCount() > 1) {
                errorQuestion.setErrorCount(errorQuestion.getErrorCount() - 1);
                this.update(errorQuestion);
            }else{
                this.delete(id);
            }

        }
    }

    /**
     * 按班级或学生查询错题
     * @author 赵文博
     * @date 2021/5/14 9:51
     * @param page
     * @param bean
     * @return java.util.List<com.xh.bussiness.exam.bean.dto.UserErrorQuestionDto>
     **/
    @Override
    public XhPage<UserErrorQuestionDto> queryErrorQuestion(XhPage<UserErrorQuestionDto> page,UserErrorQuestionRequest bean) {
//        List<UserErrorQuestionDto> userErrorQuestionDtoS = this.dao.queryErrorQuestion(page,bean);
        this.dao.queryErrorQuestion(page,bean);
        List<UserErrorQuestionDto> userErrorQuestionDtoS = page.getRecords();
        for (UserErrorQuestionDto errorQuestionDto : userErrorQuestionDtoS){
            QuestionDto questionDto = questionService.getQuestion(errorQuestionDto.getQuestionId(),null, true,true,true,false,true);
            errorQuestionDto.setQuestion(questionDto);
        }
        return page;
    }

    /**
     * 查询错某道题的学生
     * @author 赵文博
     * @date 2021/5/14 9:52
     * @param bean
     * @return java.util.List<com.xh.bussiness.exam.bean.ErrorClassStudent>
     **/
    @Override
    public List<ErrorClassStudent> queryErrorStudent(UserErrorQuestionRequest bean) {
        List<ErrorClassStudent>  classStudents = this.dao.queryErrorStudent(bean);
        return classStudents;
    }
}
